package com.ctshk.rpc.cms.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SupplierStatus;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.redis.KeyUtil;
import com.ctshk.rpc.cms.constant.CmsConstant;
import com.ctshk.rpc.cms.dto.*;
import com.ctshk.rpc.cms.entity.Banner;
import com.ctshk.rpc.cms.entity.BannerPosition;
import com.ctshk.rpc.cms.entity.BannerPositionUser;
import com.ctshk.rpc.cms.entity.LinkType;
import com.ctshk.rpc.cms.mapper.BannerMapper;
import com.ctshk.rpc.cms.mapper.BannerPositionMapper;
import com.ctshk.rpc.cms.mapper.BannerPositionUserMapper;
import com.ctshk.rpc.cms.mapper.LinkTypeMapper;
import com.ctshk.rpc.cms.req.*;
import com.ctshk.rpc.cms.service.IBannerPositionService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * banner位管理表 服务实现类
 * </p>
 *
 * @author LiZhiming
 * @since 2021-04-23
 */
@DubboService
public class BannerPositionServiceImpl extends ServiceImpl<BannerPositionMapper, BannerPosition> implements IBannerPositionService {

    @Autowired
    private BannerPositionUserMapper bannerPositionUserMapper;

    @Autowired
    private BannerMapper bannerMapper;

    @DubboReference
    private ISysUserService sysUserService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private LinkTypeMapper linkTypeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(BannerPositionAddReq bannerAddReq, TokenUser tu) {
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(BannerPosition::getBannerCode, bannerAddReq.getBannerCode());
        if (baseMapper.selectCount(qw) > 0) {
            return Result.failed(SystemError.CMS_23003);
        }
        BannerPosition bannerPosition = EntityUtil.copy(bannerAddReq, BannerPosition.class);
        LocalDateTime now = LocalDateTime.now();
        Long id = IdWorker.getId();
        bannerPosition.setId(id);
        bannerPosition.setCreateId(tu.getId());
        bannerPosition.setGmtCreate(now);
        bannerPosition.setIsDeleted(IsDeletedCode.NO.getCode());
        int insert = baseMapper.insert(bannerPosition);
        //banner位新增成功后新增操作人
        if (insert > 0 && CollectionUtils.isNotEmpty(bannerAddReq.getBannerPositionUserReqs())) {
            for (BannerPositionUserReq bpur : bannerAddReq.getBannerPositionUserReqs()) {
                BannerPositionUser copy = EntityUtil.copy(bpur, BannerPositionUser.class);
                copy.setId(IdWorker.getId());
                copy.setBannerPositionId(bannerPosition.getId());
                copy.setCreateId(tu.getId());
                copy.setGmtCreate(now);
                copy.setIsDeleted(IsDeletedCode.NO.getCode());
                bannerPositionUserMapper.insert(copy);
            }
            return Result.success(id);
        }
        return Result.failed(SystemError.CMS_23000);
    }

    @Override
    public Result<List<BannerPositionDTO>> getSelectList() {
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode());
        List<BannerPosition> bannerPositions = baseMapper.selectList(qw);
        return Result.success(EntityUtil.copyList(bannerPositions, BannerPositionDTO.class));
    }

    @Override
    public PageResponse<BannerPositionListDTO> getList(BannerPositionQueryReq req) {
        Page<BannerPosition> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda().eq(req.getBannerCode() != null, BannerPosition::getBannerCode, req.getBannerCode())
                .eq(req.getBannerName() != null, BannerPosition::getBannerName, req.getBannerName())
                .eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<BannerPosition> iPage = baseMapper.selectPage(page, qw);
        List<BannerPosition> records = iPage.getRecords();
        List<BannerPositionListDTO> bpldtos = new ArrayList<>();
        //填充banner操作人
        QueryWrapper<BannerPositionUser> qwbpu = new QueryWrapper<>();
        for (BannerPosition bp : records) {
            BannerPositionListDTO copy = EntityUtil.copy(bp, BannerPositionListDTO.class);
            UserDTO userDTO = sysUserService.loadUserInfo(bp.getCreateId(), 1);
            if (userDTO != null) {
                copy.setUserName(userDTO.getCnSurname() + userDTO.getCnName());
            }
            qwbpu.clear();
            qwbpu.lambda().eq(BannerPositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(BannerPositionUser::getBannerPositionId, copy.getId());
            List<BannerPositionUser> bpus = bannerPositionUserMapper.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<BannerPositionUserDTO> bpusdtos = EntityUtil.copyList(bpus, BannerPositionUserDTO.class);
                copy.setBannerPositionUsers(bpusdtos);
            }
            bpldtos.add(copy);
        }
        PageResponse<BannerPositionListDTO> bppr = new PageResponse<>(bpldtos,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return bppr;
    }

    @Override
    public PageResponse<BannerPositionListDTO> getList2(SelectAllQueryReq req) {
        Page<BannerPosition> page = new Page<>(req.getPageNo(), req.getPageSize());
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda()
                .select(BannerPosition::getId, BannerPosition::getBannerName)
                .eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode());
        Page<BannerPosition> iPage = baseMapper.selectPage(page, qw);
        List<BannerPositionListDTO> bannerPositionListDTOS = EntityUtil.copyList(iPage.getRecords(), BannerPositionListDTO.class);
        PageResponse<BannerPositionListDTO> bppr = new PageResponse<>(bannerPositionListDTOS,
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() *
                iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        return bppr;
    }

    @Override
    public Result<BannerPositionListDTO> getBannerPositionById(Long id) {
        ValueOperations ops = redisTemplate.opsForValue();
        //先取缓存不存在就重新查
        String opsBpl = (String) ops.get(CmsConstant.CMS_BANNER_REDIS_KEY + id.toString());
        if (StringUtils.isNotBlank(opsBpl)) {
            JSONObject jsonObject = JSON.parseObject(opsBpl);
            BannerPositionListDTO bplDTO = jsonObject.toJavaObject(BannerPositionListDTO.class);
            return Result.success(bplDTO);
        }
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(BannerPosition::getId, id);
        BannerPosition bannerPosition = baseMapper.selectOne(qw);
        if (bannerPosition != null) {
            BannerPositionListDTO bpl = EntityUtil.copy(bannerPosition, BannerPositionListDTO.class);
            //填充banner图
            QueryWrapper<Banner> qwb = new QueryWrapper<>();
            qwb.lambda().eq(Banner::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Banner::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Banner::getBannerPositionId, bannerPosition.getId());
            List<Banner> listBanners = bannerMapper.selectList(qwb);
            if (listBanners != null && listBanners.size() > 0) {
                List<BannerDTO> bannerDTOS = EntityUtil.copyList(listBanners, BannerDTO.class);
                bpl.setBanners(bannerDTOS);
            }
            //填充banner操作人
            QueryWrapper<BannerPositionUser> qwbpu = new QueryWrapper<>();
            qwbpu.lambda().eq(BannerPositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(BannerPositionUser::getBannerPositionId, bannerPosition.getId());
            List<BannerPositionUser> bpus = bannerPositionUserMapper.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<BannerPositionUserDTO> bpusdtos = EntityUtil.copyList(bpus, BannerPositionUserDTO.class);
                bpl.setBannerPositionUsers(bpusdtos);
            }
            if (bpl != null) {
                //存一个缓存
                ops.set(CmsConstant.CMS_BANNER_REDIS_KEY + id.toString(), JSONObject.toJSONString(bpl));
            }
            return Result.success(bpl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }

    @Override
    public Result<BannerPositionListDTO> getBannerPositionByCode(String code) {
        ValueOperations ops = redisTemplate.opsForValue();
        QueryWrapper<BannerPosition> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerPosition::getIsDeleted, IsDeletedCode.NO.getCode())
                .eq(BannerPosition::getBannerCode, code);
        BannerPosition bannerPosition = baseMapper.selectOne(qw);
        if (bannerPosition != null) {
            //先取缓存不存在就重新查
            String opsBpl = (String) ops.get(CmsConstant.CMS_BANNER_REDIS_KEY + bannerPosition.getId().toString());
            if (StringUtils.isNotBlank(opsBpl)) {
                JSONObject jsonObject = JSON.parseObject(opsBpl);
                BannerPositionListDTO bplDTO = jsonObject.toJavaObject(BannerPositionListDTO.class);
                return Result.success(bplDTO);
            }
            BannerPositionListDTO bpl = EntityUtil.copy(bannerPosition, BannerPositionListDTO.class);
            //填充banner图
            QueryWrapper<Banner> qwb = new QueryWrapper<>();
            qwb.lambda().eq(Banner::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(Banner::getStatus, SupplierStatus.ENABLE.getCode())
                    .eq(Banner::getBannerPositionId, bannerPosition.getId());
            List<Banner> listBanners = bannerMapper.selectList(qwb);
            if (listBanners != null && listBanners.size() > 0) {
                List<BannerDTO> bannerDTOS = EntityUtil.copyList(listBanners, BannerDTO.class);
                for (BannerDTO b : bannerDTOS) {
                    QueryWrapper<LinkType> qwlt = new QueryWrapper<>();
                    qwlt.lambda().eq(LinkType::getCorrelationId, b.getId())
                            .eq(LinkType::getIsDeleted, IsDeletedCode.NO.getCode());
                    LinkType linkType = linkTypeMapper.selectOne(qwlt);
                    if (linkType != null) {
                        b.setLinkTypeDto(EntityUtil.copy(linkType, LinkTypeDTO.class));
                    }
                }
                bpl.setBanners(bannerDTOS);
            }
            //填充banner操作人
            QueryWrapper<BannerPositionUser> qwbpu = new QueryWrapper<>();
            qwbpu.lambda().eq(BannerPositionUser::getIsDeleted, IsDeletedCode.NO.getCode())
                    .eq(BannerPositionUser::getBannerPositionId, bannerPosition.getId());
            List<BannerPositionUser> bpus = bannerPositionUserMapper.selectList(qwbpu);
            if (CollectionUtils.isNotEmpty(bpus)) {
                List<BannerPositionUserDTO> bpusdtos = EntityUtil.copyList(bpus, BannerPositionUserDTO.class);
                bpl.setBannerPositionUsers(bpusdtos);
            }
            if(bpl != null){
                //存一个缓存
                ops.set(CmsConstant.CMS_BANNER_REDIS_KEY + bannerPosition.getId().toString(), JSONObject.toJSONString(bpl));
            }
            return Result.success(bpl);
        } else {
            return Result.failed(SystemError.CMS_23001);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result update(BannerPositionUpdateReq req, TokenUser tu) {
        BannerPosition bp = EntityUtil.copy(req, BannerPosition.class);
        LocalDateTime now = LocalDateTime.now();
        bp.setModifiedId(tu.getId());
        bp.setGmtModified(now);
        int i = baseMapper.updateById(bp);
        //更新修改的操作人(操作人这种变动频繁的就不使用逻辑删除了，直接干掉从新添加)
        if (i > 0) {
            if (CollectionUtils.isNotEmpty(req.getBannerPositionUsers())) {
                QueryWrapper<BannerPositionUser> qw = new QueryWrapper<>();
                qw.lambda().eq(BannerPositionUser::getBannerPositionId, req.getId());
                bannerPositionUserMapper.delete(qw);
                //将新的操作人添加入库
                List<BannerPositionUserDTO> bannerPositionUsers = req.getBannerPositionUsers();
                for (BannerPositionUserDTO bpu : bannerPositionUsers) {
                    BannerPositionUser copy = EntityUtil.copy(bpu, BannerPositionUser.class);
                    copy.setId(IdWorker.getId());
                    copy.setBannerPositionId(req.getId());
                    copy.setCreateId(tu.getId());
                    copy.setGmtCreate(now);
                    copy.setIsDeleted(IsDeletedCode.NO.getCode());
                    bannerPositionUserMapper.insert(copy);
                }
            }
            //做了修改操作如果存在这个缓存就清除缓存
            Set<String> keysRecommend = redisTemplate.keys(KeyUtil.genLikeKey(CmsConstant.CMS_BANNER_REDIS_KEY));
            if (CollUtil.isNotEmpty(keysRecommend)) {
                redisTemplate.delete(keysRecommend);
            }
            return Result.success(req.getId());
        }
        return Result.failed(SystemError.CMS_23002);
    }
}
